package common;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by dave on 16/11/3.
 */
@RestControllerAdvice
public class AppControllerAdvice {
    private static final Logger LOG = LoggerFactory.getLogger(AppControllerAdvice.class);

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.OK)
    public JsonMessage<Map<String, String>> argumentException(MethodArgumentNotValidException e) {
        return parseBindResult(e.getBindingResult());
    }

    @ExceptionHandler(BindException.class)
    @ResponseStatus(HttpStatus.OK)
    public JsonMessage<Map<String, String>> bindException(BindException e) {
        return parseBindResult(e.getBindingResult());
    }

    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseStatus(HttpStatus.OK)
    public JsonMessage<Map<String, String>> constraintViolationException(ConstraintViolationException e) {
        Map<String, String> errors = new HashMap<>();
        e.getConstraintViolations().forEach(v -> {
            errors.put(v.getPropertyPath().toString(), v.getMessage());
        });
        return new JsonMessage<>(false, "数据校验失败", "RESOLVE_PARAM_ERROR", errors);
    }

    @ExceptionHandler(MissingServletRequestParameterException.class)
    @ResponseStatus(HttpStatus.OK)
    public JsonMessage<String> badRequest(MissingServletRequestParameterException e) {
        return new JsonMessage<>(false, e.getMessage(), "MISSING_PARAMETER");
    }

    @ExceptionHandler(ErrorOccurredException.class)
    @ResponseStatus(HttpStatus.OK)
    public JsonMessage<String> warnException(ErrorOccurredException e) {
        return new JsonMessage<>(false, e.getMessage(), "ERROR_MESSAGE");
    }

    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.OK)
    public JsonMessage<String> exception(Exception e) {
        LOG.warn("出现异常", e);
        String msg = e.getMessage();
        if (msg == null || msg.isEmpty()) {
            msg = e.getClass().getCanonicalName();
        }
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes != null) {
            HttpServletRequest request = attributes.getRequest();
            request.setAttribute("HANDLER_EXCEPTION", e);
        }
        return new JsonMessage<>(false, msg, "INTERNAL_EXCEPTION");
    }

    private JsonMessage<Map<String, String>> parseBindResult(BindingResult r) {
        Map<String, String> errors = new HashMap<>();
        r.getAllErrors().forEach(i -> {
            Map<String, String> ret = new HashMap<>();
            String code0 = i.getCodes()[0];
            errors.put(code0.substring(code0.lastIndexOf(".") + 1), i.getDefaultMessage());
        });

        return new JsonMessage<>(false, "数据输入错误", "RESOLVE_PARAM_ERROR", errors);
    }
}
